<?php
/**
 * Author:   tangxiaowen
 * Email:    846506584@qq.com
 * Date:     2019/3/13 0013
 * Describe: ping++支付
 */

namespace app\index\controller;

class Ping extends Base
{

    public function __construct()
    {
        parent::__construct();

        //初始化获取ping++配置文件
        $this->initPingConfig();
    }

    /**
     * ping支付
     * @param string $title 支付名称
     * @param string $orderSn 支付订单号
     * @param int $amount 支付金额/元
     * @param string $alipay 支付渠道/微信|支付宝
     * @param string $describe 支付备注
     * @return object
     */
    public function pay($title,$orderSn,$amount,$alipay = 'alipay',$describe = '')
    {
        //引入ping SDK类库 初始化ping配置
        import('pingpp.init');
        \Pingpp\Pingpp::setPrivateKeyPath($this->pingConfig['privateKeyPath']);//私钥文件
        \Pingpp\Pingpp::setApiKey($this->pingConfig['apiKey']); //私钥apiKey

        //生成新单号，保证每次请求ping都用新单号
        $pingOrderSn = $orderSn . rand(000000,999999);
        $savePingResult = $this->addPingLog($orderSn,$pingOrderSn);
        if(!$savePingResult){
            returnErrorResult('业务繁忙，稍后再试');
        }

        try {
            //支付数据
            $payData = [
                'subject'   => $title,         //商品标题
                'order_no'  => $pingOrderSn,   //商品单号
                'amount'    => $amount*100,    //支付金额/分
                'app'       => array(
                    'id' => $this->pingConfig['appId'],
                ),                              //商户AppId
                'channel'   => $alipay,         //支付渠道 alipay支付宝支付 wx微信支付(暂时仅限这两种)
                'currency'  => 'cny',           //支付货币代码 cny人民币
                'client_ip' => request()->ip(), //请求的客户端IP
                'body'      => $describe,       //商品描述
            ];

            //创建支付请求
            $result = \Pingpp\Charge::create($payData);

        } catch (\Pingpp\Error\Base $e) {
            // 捕获报错信息
            returnErrorResult($e->getMessage());
        }

        $json_string2 = json_encode($result, JSON_FORCE_OBJECT);
        \Think\Log::record('ping++创建Charges返回给客户端的参数');
        \Think\Log::record($json_string2);

        //返回给Charges对象
        returnSuccessResult($json_string2);
    }

    /**
     * 支付回调
     */
    public function payCallback()
    {
        $event = json_decode(file_get_contents("php://input"));
        \Think\Log::record('ping++创建Charges的回调数据');
        \Think\Log::record(json_encode($event,JSON_UNESCAPED_UNICODE));

        //对异步通知做处理
        if (!isset($event->type)) {
            header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
            \Think\Log::record('ping++ 用户还款支付回调 fail');
            exit("fail");
        }
        $result = false;
        switch ($event->type) {
            case "charge.succeeded":

                // 开发者在此处加入对支付异步通知的处理代码
                header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
                //回调数据
                $result = $this->payCallbackSuccess($event->data);
                break;
            case "refund.succeeded":
                // 开发者在此处加入对退款异步通知的处理代码
                header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
                \Think\Log::record('ping++ 用户还款支付回调 refund.succeeded');
                break;
            default:
                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
                \Think\Log::record('ping++ 用户还款支付回调 default');
                break;
        }

        if($result){
            \Think\Log::record('ping++ 用户还款支付回调 返回给ping结果-成功');
            echo '成功';
        }else{
            \Think\Log::record('ping++ 用户还款支付回调 返回给ping结果-不返回');
        }
    }

    /**
     * 用户还款支付-处理回调
     * @param array $callbackData ping++回调的成功数据(支付数据[订单单号，支付金额等])
     * @return bool
     */
    public function payCallbackSuccess($callbackData)
    {
        $channel = '';
        switch ($callbackData->object->channel){
            case 'alipay':
                $channel = 5;//支付宝
                break;
            case 'wx':
                $channel = 4;//微信
                break;
        }

        $result = false;
        if($callbackData->object->subject == '用户还款'){
            $result = (new Order())->orderPayTwo($callbackData->object->order_no,$callbackData->object->amount/100,$callbackData->object->time_paid,$callbackData->object->id,$channel);
        }

        if($callbackData->object->subject == '用户展期'){
            $result = (new Order())->orderStageTwo($callbackData->object->order_no,$callbackData->object->amount/100,$callbackData->object->time_paid,$callbackData->object->id,$channel);
        }

        return $result;
    }

    /**
     * 获取ping配置信息
     * @return array
     */
    private function initPingConfig()
    {
        $data = db('sys_integrate')->alias('i')
            ->join('xb_sys_inteparameter n','i.ID = n.IntegrateID')
            ->where(['i.EName' => 'pinjiajia'])
            ->select();

        if(!$data){
            returnErrorResult('尚未配置支付环境');
        }

        $temp = [];
        foreach ($data as $k=>$v){
            $temp[$v['ParaName']] = $v['ParaValue'];
        }

        if(!$temp || !isset($temp['apiKey']) || empty($temp['apiKey'])){
            returnErrorResult('缺少apiKey配置');
        }elseif(!$temp || !isset($temp['appId']) || empty($temp['appId'])){
            returnErrorResult('缺少appId配置');
        }elseif(!$temp || !isset($temp['privateKeyPath']) || empty($temp['privateKeyPath'])){
            returnErrorResult('缺少私钥文件配置');
        }

        $this->pingConfig = $temp;
    }

    /**
     * 创建Ping++支付记录的订单号
     * @param string $orderSn 订单编号
     * @param string $pingOrderSn ping订单编号
     * @return bool
     */
    private function addPingLog($orderSn,$pingOrderSn)
    {
        $tempPing = [
            'OrderSn' => $orderSn,
            'PingOrderSn' => $pingOrderSn,
            'CreateTime' => date('Y-m-d H:i:s',time()),
        ];
        return db('pay_ping')->insert($tempPing);
    }

    /**
     * 获取ping支付记录的关联订单信息
     * @param int $pingOrderId ping支付单号ID
     * @return array
     */
    private function getPingOrder($pingOrderId)
    {
        return db('pay_ping')->where(['PingOrderSn' => $pingOrderId])->find();
    }

    /**
     * 插入支付记录
     * @param int $orderId 订单ID
     * @param int $userId 用户ID
     * @param string $orderSn 订单编号
     * @param string $tradeNo 交易流水号
     * @param integer $type 支付状态
     * @param integer $amount 支付金额
     * @param integer $channel 支付方式
     * @param integer $CreateTime 支付时间
     * @return bool
     */
    public function addPay($orderId,$userId,$orderSn,$tradeNo,$type,$amount,$channel,$CreateTime)
    {
        $payData = [
            'AppID'       => $orderId,
            'UserID'      => $userId,
            'OrderSn'     => $orderSn,
            'TradeNo'     => $tradeNo,
            'Type'        => $type,
            'OrderAmount' => $amount,
            'pay'         => $channel,
            'CreateTime'  => date('Y-m-d H:i:s',$CreateTime),
        ];
        return db('loans_paylist')->insert($payData);
    }

}